package com.example.zcapi;

import static com.blankj.utilcode.util.PathUtils.getInternalAppCachePath;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.multidex.MultiDex;

import com.arialyy.aria.core.Aria;
import com.blankj.utilcode.util.LogUtils;
import com.example.zcapi.http.ReleaseServer;
import com.example.zcapi.http.model.RequestHandler;
import com.github.gzuliyujiang.oaid.DeviceIdentifier;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonToken;
import com.hjq.http.EasyConfig;
import com.hjq.http.config.IRequestInterceptor;
import com.hjq.http.config.IRequestServer;
import com.hjq.http.model.HttpHeaders;
import com.hjq.http.model.HttpParams;
import com.hjq.http.request.HttpRequest;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.smtt.export.external.TbsCoreSettings;
import com.tencent.smtt.sdk.QbSdk;

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;

import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.AutoSizeConfig;
import me.jessyan.autosize.DefaultAutoAdaptStrategy;
import me.jessyan.autosize.onAdaptListener;
import okhttp3.OkHttpClient;


public class MqttApp extends Application {

    private String TAG = MqttApp.class.getName();
    private static MqttApp instance;

    private int orientation = 0;

    public static MqttApp getInstance() {
        return instance;
    }


    @Override
    public void onCreate() {
        super.onCreate();
        LogUtils.d(TAG,"MqttApp onCreate");
        instance = this;
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler(this));
//        CustomToast.init(this);
        MultiDex.install(this);
        Aria.init(this);

        LogUtils.d(TAG,"MqttApp onCreate a");

        HashMap<String, Object> map = new HashMap<>();
        map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true);
        map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true);
        QbSdk.initTbsSettings(map);
        QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() {
            @Override
            public void onCoreInitFinished() {
            }
            @Override
            public void onViewInitFinished(boolean b) {
            }
        });

//        int height = CommonUtil.getScreenHeight(this);
//        int width = CommonUtil.getScreenWidth(this);
//        if (width > height) {
//            orientation = 0;
//        }else {
//            orientation = 1;
//        }
        if(Configs.DEBUG){
//            AppConfig.setDeviceId("1468B79E73031416");
//            AppConfig.setOrgId(50);
        }
        LogUtils.d(TAG,"orientation" + orientation);
        AppConfig.setOrientation(orientation);
//        AppConfig.setOrientation(0);
        DeviceIdentifier.register(this);
//        GlideUtils.initGlide();
//        CrashReport.initCrashReport(this, "1c34b78fb7", false)
        AutoSize.initCompatMultiProcess(this);
        AutoSizeConfig.getInstance() //是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
                //如果没有这个需求建议不开启
                .setDesignWidthInDp(375)
                .setDesignHeightInDp(800)
                .setAutoAdaptStrategy(new DefaultAutoAdaptStrategy())
                .setExcludeFontScale(true)
                .setCustomFragment(false) //是否屏蔽系统字体大小对 AndroidAutoSize 的影响, 如果为 true, App 内的字体的大小将不会跟随系统设置中字体大小的改变
                //如果为 false, 则会跟随系统设置中字体大小的改变, 默认为 false
                .setExcludeFontScale(false).setOnAdaptListener(new onAdaptListener() {
                    @Override
                    public void onAdaptBefore(Object o, Activity activity) {
                    }
                    @Override
                    public void onAdaptAfter(Object o, Activity activity) {
                    }
                });
//        AppConfig.setEnv(Configs.Env);
        CrashReport.initCrashReport(this, "d5799eccd3", false);
        AppConfig.setPowerTurnType(-1);
        LogUtils.d(TAG,"MqttApp onCreate b");

        if(Configs.cacheByProxy){
//            if(USE_MEDIA_MOUNTED){
//                if (Objects.equals(Environment.getExternalStorageState(), MEDIA_MOUNTED)) {
//                    fileCachePath = FileUtil.getExternalStorageDir() + "/"+ AppUtils.getAppName();
//                }else{
//                    fileCachePath = PathUtils.getInternalAppCachePath();
//                }
//            }else {
//                fileCachePath = PathUtils.getInternalAppCachePath();
//            }
//
//            File saveFile = new File(fileCachePath);
//            if (!saveFile.exists()) {
//                saveFile.mkdir();
//            }
//            VideoProxyCacheManager.Builder cacheBuilder = new VideoProxyCacheManager.Builder().
//                    setFilePath(fileCachePath).
//                            setConnTimeOut(90 * 1000).
//            GsonFactory.setParseExceptionCallback(new ParseExceptionCallback() {
//
//                @Override
//                public void onParseObjectException(TypeToken<?> typeToken, String fieldName, JsonToken jsonToken) {
//                    handlerGsonParseException("解析对象析异常：" + typeToken + "#" + fieldName + "，后台返回的类型为：" + jsonToken);
//                }
//
//                @Override
//                public void onParseListItemException(TypeToken<?> typeToken, String fieldName, JsonToken listItemJsonToken) {
//                    handlerGsonParseException("解析 List 异常：" + typeToken + "#" + fieldName + "，后台返回的条目类型为：" + listItemJsonToken);
//                }
//
//                @Override
//                public void onParseMapItemException(TypeToken<?> typeToken, String fieldName, String mapItemKey, JsonToken mapItemJsonToken) {
//                    handlerGsonParseException("解析 Map 异常：" + typeToken + "#" + fieldName + "，mapItemKey = " + mapItemKey + "，后台返回的条目类型为：" + mapItemJsonToken);
//                }
//
//                private void handlerGsonParseException(String message) {
//                    if (BuildConfig.DEBUG) {
//                        throw new IllegalArgumentException(message);
//                    }  else {
//                        CrashReport.postCatchedException(new IllegalArgumentException(message));
//                    }
//                }
//            });

            // 网络请求框架初始化
            IRequestServer server;
            server = new ReleaseServer();

            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .build();

            EasyConfig.with(okHttpClient)
                    // 是否打印日志
                    .setLogEnabled(BuildConfig.DEBUG)
                    // 设置服务器配置（必须设置）
                    .setServer(server)
                    // 设置请求处理策略（必须设置）
                    .setHandler(new RequestHandler(this))
                    // 设置请求参数拦截器
                    .setInterceptor(new IRequestInterceptor() {
                        @Override
                        public void interceptArguments(@NonNull HttpRequest<?> httpRequest,
                                                       @NonNull HttpParams params,
                                                       @NonNull HttpHeaders headers) {
                            headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
                        }
                    })
                    // 设置请求重试次数
                    .setRetryCount(3)
                    // 设置请求重试时间
                    .setRetryTime(1000 * 30)
                    // 添加全局请求参数
//                    .addParam("token", "6666666")
                    // 添加全局请求头
                    //.addHeader("date", "20191030")
                    .into();



        }else {
//            WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);
//            WebViewCacheInterceptorInst.getInstance().init(builder);
        }
        LogUtils.d(TAG,"MqttApp onCreate c");
    }

    private static class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

        private Context context;

        private Thread.UncaughtExceptionHandler mDefaultHandler;

        public MyUncaughtExceptionHandler(Context context) {
            this.context = context;
            mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            //设置该CrashHandler为程序的默认处理器
            Thread.setDefaultUncaughtExceptionHandler(this);
        }

        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            if (!handleException(ex) && mDefaultHandler != null) {
                //如果用户没有处理则让系统默认的异常处理器来处理
                mDefaultHandler.uncaughtException(thread, ex);
            } else {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    com.blankj.utilcode.util.LogUtils.e("error : ", e);
                    e.printStackTrace();
                }finally {
//                    RestartApp.restartApplication(context);
                }
//                //退出JVM(java虚拟机),释放所占内存资源,0表示正常退出(非0的都为异常退出)
//                System.exit(0);
//                //从操作系统中结束掉当前程序的进程
//                android.os.Process.killProcess(android.os.Process.myPid());

            }
        }
    }

    /**
     * 自定义错误处理,收集错误信息
     * 发送错误报告等操作均在此完成.
     * 开发者可以根据自己的情况来自定义异常处理逻辑
     * @return
     * true代表处理该异常，不再向上抛异常，
     * false代表不处理该异常(可以将该log信息存储起来)然后交给上层(这里就到了系统的异常处理)去处理，
     * 简单来说就是true不会弹出那个错误提示框，false就会弹出
     */
    private static boolean handleException(final Throwable ex) {
        if (ex == null) {
            return false;
        }
//        final String msg = ex.getLocalizedMessage();
        final StackTraceElement[] stack = ex.getStackTrace();
        final String message = ex.getMessage();
        //使用Toast来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
//                Toast.makeText(mContext, "程序出错啦:" + message, Toast.LENGTH_LONG).show();
//                可以只创建一个文件，以后全部往里面append然后发送，这样就会有重复的信息，个人不推荐
                String rootPath = getInternalAppCachePath();
                String crashName = "crash-" + System.currentTimeMillis()  + ".log";
                File file = new File(rootPath,crashName);
//                CrashConfig.setInfo(crashName);
                try {
                    FileOutputStream fos = new FileOutputStream(file,true);
                    fos.write(message.getBytes());
                    for (int i = 0; i < stack.length; i++) {
                        fos.write(stack.toString().getBytes());
                    }
                    fos.flush();
                    fos.close();
                } catch (Exception e) {
                }
                Looper.loop();
            }
        }.start();
        return false;
    }

}
